package puzzle.hashikake.data;

import java.util.ArrayList;
import java.util.List;

import puzzle.common.data.AbstractBoard;
import puzzle.common.point.Pnt;

public class HashikakeBoard extends AbstractBoard<HashikakeBoard> {
	private BoardDef m_def;
	
	private List<HashiState> m_hashiStates;
	
	public HashikakeBoard(int w, int h) {
		super(w, h);
		m_def = new BoardDef(w, h);
		m_hashiStates = new ArrayList<HashiState>();
	}
	
	public HashikakeBoard(HashikakeBoard other) {
		super(other);
		m_def = other.m_def; // no need to dup
		m_hashiStates = new ArrayList<HashiState>(other.m_hashiStates.size());
		copyFromImpl(other);
	}

	@Override
	protected void copyFromImpl(HashikakeBoard other) {
		assert m_def == other.m_def;
		m_hashiStates.clear();
		for (HashiState s : other.m_hashiStates) {
			m_hashiStates.add(s.dup(this));
		}
	}

	@Override
	public HashikakeBoard dup() {
		return new HashikakeBoard(this);
	}

	@Override
	public void snapshotDirtyFlags() {
	}
	
	public List<HashiState> getHashiStates() {
		return m_hashiStates;
	}
	
	public HashiState[] getHashiStatesForShima(ShimaDef shima) {
		HashiState[] result = new HashiState[shima.getHashis().size()];
		for (int i = 0; i < result.length; i++) {
			HashiDef hashi = shima.getHashis().get(i);
			result[i] = m_hashiStates.get(hashi.i);
		}
		return result;
	}
	
	public HashiState getHashiState(int index) {
		return m_hashiStates.get(index);
	}

	public void addShima(int x, int y, int targetNumber) {
		m_def.addShima(x, y, targetNumber);
	}

	public ShimaDef getShima(int x, int y) {
		return m_def.getShima(x, y);
	}

	public ShimaDef getShima(Pnt p) {
		return m_def.getShima(p);
	}

	public HashiDef addHashi(ShimaDef s1, ShimaDef s2) {
		HashiDef hashi = m_def.addHashi(s1, s2);
		m_hashiStates.add(new HashiState(this, hashi));
		return hashi;
	}

	public HashiDef getHashi(int index) {
		return m_def.getHashi(index);
	}

	public List<ShimaDef> getShimaList() {
		return m_def.getShimaList();
	}
	
	public boolean isShimaSatisfied(ShimaDef shima) {
		HashiState[] hashiStates = getHashiStatesForShima(shima);
		int totalNubmer = 0;
		for (HashiState s : hashiStates) {
			totalNubmer += s.isFixed() ? s.getNumber() : 0;
		}
		return shima.n == totalNubmer;
	}

}
